package project;

import java.net.URL;
import java.net.URLConnection;

import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.util.NodeIterator;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

/**
 * The workhorse class of the data collection module. This class will parse the HTML data from Yahoo! Finance
 * and return the desired values.
 * @author henry
 *
 */
public class InfoCollector {
        
        //Default URL for all HTML requests. We will be collecting financial data from Yahoo! Finance
        private static String url = "http://finance.yahoo.com/q?s=";
        
        /**
         * Returns the current stock information from Yahoo! Finance
         * @param stock The symbol of the stock
         * @return A StockInfo object, containing the latest stock price and the latest trading volume
         * @throws Exception
         */
        public static StockInfo getCurrentStockInfo(String stock) throws Exception{
                
                // Checks to see if it is a valid stock name by its length. Valid stock names have exactly 4 characters
                /*if(stock.length() != 4)
                        return null;*/
                
                // Creates a connection to the webpage for the stock
                URLConnection uc = (new URL(url+stock)).openConnection();
                                
                //Parses the HTML page, filters to find the elements we are interested in, then stores it in an array
                Node[] n = ParseHTML(uc).toNodeArray();

                //displayNodes(n);      //For debugging purposes
                
                //Parsed HTML data is stored as a tree. Thus, tree traversals are necessary to find the desired data.
                //NOTE: If the data collected appears to be incorrect, this is the first place to look. If Yahoo
                //              changes their website layout, then the tree structure is no longer the same, and the tree traversal
                //              must be adjusted accordingly
                
                Double lastTrade = Double.parseDouble(n[0].getFirstChild().getNextSibling().getNextSibling().getFirstChild().getText());
                
                Double changePrice = lastTrade - Double.parseDouble(n[3].getFirstChild().getText());
                
                /*
                if(n[2].getFirstChild().getFirstChild().getText().contains("alt=\"Up\""))
                        changePrice = Double.parseDouble(n[2].getFirstChild().getFirstChild().getNextSibling().getNextSibling().getNextSibling().getText());
                else {
                        changePrice = Double.parseDouble(n[2].getFirstChild().getFirstChild().getNextSibling().getNextSibling().getNextSibling().getText());
                        changePrice = -changePrice;
                }
                */
                
                String volumeString = (n[10].getLastChild().getLastChild().getText());
                Integer volume = Integer.parseInt(volumeString.replace(",", ""));
                                
                return new StockInfo(lastTrade, changePrice, volume);
        }
        
        /**
         * Returns the final stock information for the day from Yahoo! Finance
         * @param stock The symbol of the stock
         * @return A StockInfo object, containing opening price for the day, closing price of the day,
         * highest price of the day, lowest price of the day, latest trade volume, change in price, 
         * the pe, and the eps
         * @throws Exception
         */
        public static StockInfo getFinalStockInfo(String stock) throws Exception{
                // Checks to see if it is a valid stock name by its length. Valid stock names have exactly 4 characters
                /*if(stock.length() != 4)
                        return null;*/
                
                // Creates a connection to the webpage for the stock
                URLConnection uc = (new URL(url+stock)).openConnection();
                                
                //Parses the HTML page, filters to find the elements we are interested in, then stores it in an array
                Node[] n = ParseHTML(uc).toNodeArray();
                
                //displayNodes(n);      //For debugging purposes
                
                //Parsed HTML data is stored as a tree. Thus, tree traversals are necessary to find the desired data.
                //NOTE: If the data collected appears to be incorrect, this is the first place to look. If Yahoo
                //              changes their website layout, then the tree structure is no longer the same, and the tree traversal
                //              must be adjusted accordingly
                
                String openString = n[4].getLastChild().getText();
                Double openPrice = -1.0;
                if(!openString.equals("N/A"))
                	openPrice = Double.parseDouble(n[4].getLastChild().getText());
                
                Double closePrice = Double.parseDouble(n[0].getFirstChild().getNextSibling().getNextSibling().getFirstChild().getText());
                Double highPrice = Double.parseDouble(n[8].getFirstChild().getNextSibling().getNextSibling().getFirstChild().getFirstChild().getText());
                Double lowPrice = Double.parseDouble(n[8].getFirstChild().getFirstChild().getFirstChild().getText());
                
                String volumeString = (n[10].getLastChild().getLastChild().getText());
                Integer volume = Integer.parseInt(volumeString.replace(",", ""));
                
                Double changePrice = closePrice - Double.parseDouble(n[3].getFirstChild().getText());
                
                String peString = n[13].getFirstChild().getText();
                System.out.println("----***---" + peString);
                Double peValue = -1.0;
                if(!peString.equals("N/A"))
                	peValue = Double.parseDouble(n[13].getFirstChild().getText());
                
                String epsString = n[14].getFirstChild().getText();
                Double epsValue = -1.0;
                if(!epsString.equals("N/A"))
                	epsValue = Double.parseDouble(n[14].getFirstChild().getText());
                
                return new StockInfo(openPrice, closePrice, highPrice, lowPrice, volume, changePrice, peValue, epsValue);
        }
        
        /**
         * Returns the current market information from Yahoo! Finance
         * @param market The symbol of the market
         * @return A MarketInfo object, containing the current value of the market and the latest change
         * @throws Exception
         */
        public static MarketInfo getCurrentMarketInfo(String market) throws Exception{
                // Checks to see if it is a valid market name by its length. Valid stock names have at most 4 characters with a carrot in front
                if(market.length() > 5)
                        return null;
                
                // Creates a connection to the webpage for the stock
                URLConnection uc = (new URL(url+market)).openConnection();
                
                //Parses the HTML page, filters to find the elements we are interested in, then stores it in an array
                Node[] n = ParseHTML(uc).toNodeArray();
                
                //displayNodes(n);      //For debugging purposes
                
                //Parsed HTML data is stored as a tree. Thus, tree traversals are necessary to find the desired data.
                //NOTE: If the data collected appears to be incorrect, this is the first place to look. If Yahoo
                //              changes their website layout, then the tree structure is no longer the same, and the tree traversal
                //              must be adjusted accordingly
                
                String currentString = n[0].getFirstChild().getNextSibling().getNextSibling().getFirstChild().getText();
                Double current = Double.parseDouble(currentString.replace(",", ""));
                
                String changeString = n[3].getFirstChild().getText();
                Double change = current - Double.parseDouble(changeString.replace(",", ""));

                /*
                if(n[2].getFirstChild().getFirstChild().getText().contains("alt=\"Up\"")){
                        changeString = n[2].getFirstChild().getFirstChild().getNextSibling().getNextSibling().getNextSibling().getText();
                        change = Double.parseDouble(changeString.replace(",", ""));
                } else {
                        changeString = n[2].getFirstChild().getFirstChild().getNextSibling().getNextSibling().getNextSibling().getText();
                        change = Double.parseDouble(changeString.replace(",", ""));
                        change = -change;
                }
                */
                                
                return new MarketInfo(current, change);
        }
        
        public static MarketInfo getFinalMarketInfo(String market) throws Exception{
                // Checks to see if it is a valid market name by its length. Valid stock names have at most 4 characters with a carrot in front
                if(market.length() > 5)
                        return null;
                
                // Creates a connection to the webpage for the stock
                URLConnection uc = (new URL(url+market)).openConnection();
                
                //Parses the HTML page, filters to find the elements we are interested in, then stores it in an array
                Node[] n = ParseHTML(uc).toNodeArray();
                
                //displayNodes(n);      //For debugging purposes
                
                //Parsed HTML data is stored as a tree. Thus, tree traversals are necessary to find the desired data.
                //NOTE: If the data collected appears to be incorrect, this is the first place to look. If Yahoo
                //              changes their website layout, then the tree structure is no longer the same, and the tree traversal
                //              must be adjusted accordingly
                
                String openString = n[4].getFirstChild().getText();
                Double open = Double.parseDouble(openString.replace(",", ""));
                String closeString = n[0].getFirstChild().getNextSibling().getNextSibling().getFirstChild().getText();
                Double close = Double.parseDouble(closeString.replace(",", ""));
                
                String changeString = n[3].getFirstChild().getText();
                Double change = close - Double.parseDouble(changeString.replace(",", ""));

                /*
                if(n[2].getFirstChild().getFirstChild().getText().contains("alt=\"Up\"")){
                        changeString = n[2].getFirstChild().getFirstChild().getNextSibling().getNextSibling().getNextSibling().getText();
                        change = Double.parseDouble(changeString.replace(",", ""));
                } else {
                        changeString = n[2].getFirstChild().getFirstChild().getNextSibling().getNextSibling().getNextSibling().getText();
                        change = Double.parseDouble(changeString.replace(",", ""));
                        change = -change;
                }
                */
                                
                return new MarketInfo(open, close, change);
        }
        
        /**
         * Parses the HTML data for a given URLConnection type
         * @param connect A URLConnection type
         * @return A NodeList containing all the HTML tags with an attribute of class="yfnc_tabledata1"
         * @throws ParserException
         */
        private static NodeList ParseHTML(URLConnection connect) throws ParserException{
                Parser p = new Parser();
                p.setConnection(connect);
                NodeList nl = new NodeList();
                
                //Filters the HTML page by looking at tags with an attribute of class="yfnc_tabledata1",
                //then storing those tags into the NodeList. This reduces the hundreds of tags on the 
                //page down to the few that we are interested in.
                HasAttributeFilter haf = new HasAttributeFilter("class", "yfnc_tabledata1");
                for(NodeIterator e = p.elements(); e.hasMoreNodes();){
                        e.nextNode().collectInto(nl, haf);
                }
                
                return nl;
        }
        
        @SuppressWarnings("unused")
        private static void displayNodes(Node[] n){
                for(int i = 0; i < n.length; i++){
                        System.out.println(i+" "+n[i].toString());
                }
        }

}
